/*
 * edbd.h - edbd header file
 *        - definitions & declarations of variables & functions
 * Clunix, glory@clunix.com, 2001.8.16.
 * Clunix, cezanne@clunix.com, 2005.2
 *
 * Copyright (c) 2001-2005 by Clunix Inc. All Rights Reserved.
 */

#ifndef _EDBD_H_
#define _EDBD_H_

#include "sr.h"
#include "ebc.h"
#include "edb.h"
#include "eds.h"
#include "edl.h"
#include "edb_proto.h"

#define EDBD_VERSION			0x000400

#define EDBD_ENV_MODNAME		"CLX_EDBD_MODNAME"
#define EDBD_ENV_MODVER			"CLX_EDBD_MODVER"
#define EDBD_DEFAULT_MODNAME		"edbd"
#define EDBD_DEFAULT_SNAPSHOT		"snapshot"
#define EDBD_INITIAL_SNAPSHOT		"snapshot.init"

#define IS_MASTER()		(self_msid == self_ndid)
#define EXIST_MASTER()		(self_msid != 0)
#define IS_SLAVE()		(self_msid != self_ndid)

#define EDBD_IS_SELF_NDID(ndid)	((ndid) == self_ndid || (ndid) == EBC_NDID_SELF)

/* used by edbd_create_cl_tree() in edbd_init_tree.c */
#define EDBD_DEFAULT_TIMESERVER	    "time.bora.net"

/* flags for saving system time to hardware clock */
#define ON_ECM_START		1
#define ON_ECM_END		2
#define DEPEND_ON_SETUP		4

typedef void *edbd_bdexpr_t;
typedef void *edbd_lnpsensor_infos_t;

extern sr_t		*sr_edbd_conf;
extern sr_t		*sr_edbroot;
extern sr_t		*sr_edbd_xe_forms;

#define TREELOCK_VALID_MASK	0x8000

#ifdef ECM_DEBUG

#define TREE_LOCK_ASSERT(sr, type)	ECMASSERT(tree_lock(sr, type))
#define GET_TREE_LOCK_ASSERT(sr, type)	ECMASSERT(get_tree_lock(sr, type))

#else

#define TREE_LOCK_ASSERT(sr, type)	tree_lock(sr, type)
#define GET_TREE_LOCK_ASSERT(sr, type)	get_tree_lock(sr, type)

#endif

typedef enum {
	PRECUR_EX_LOCK = 0,
	RECUR_EX_LOCK,
	EX_LOCK,
	RECUR_SH_LOCK,
	SH_LOCK,
	PIN_LOCK,
	PIN_FREE_LOCK = 100,
	PIN_VALID_LOCK = PIN_LOCK | TREELOCK_VALID_MASK,
} treelock_t;

typedef enum {
	NEED_ELECTION,
	DETECTING_MASTER,
	ANNOUNCING_MASTER,
	IMPORTING_SNAPSHOT,
	MASTER_ELECTED,
} election_state_t;

extern election_state_t	election_state;

extern ebc_clid_t	self_clid;
extern ebc_ndid_t	self_ndid, self_msid;
extern ebc_mdid_t	self_mdid;
extern xid_t		self_node_xid;

extern char	*self_clname, *self_ndname, *self_msname;

extern ECMBOOL		edbd_master_enabled;

extern ecm_uint32	master_detection_time;
extern ecm_uint32	master_announce_time;
extern ecm_uint32	master_detection_retry;
extern ecm_uint32	master_announce_retry;
extern ecm_uint32	heartbeat_miss_time;
extern ecm_uint32	snapshot_interval;

#ifdef ECM_DEBUG

#ifdef NO_EDBDDBG

#define EDBDDBG(dbgset, fmt, ...)	do {} while(0)

#else

extern ecm_dbg_t	edbd_dbg;

#define DBG_EDBD		0x0001
#define DBG_SNAPSHOT		0x0002
#define DBG_ELECT		0x0004
#define DBG_CLIREQ		0x0008
#define DBG_ECXUI		0x0010
#define DBG_INIT		0x0020
#define DBG_CONN		0x0040
#define DBG_UPDATE		0x0080
#define DBG_REACTOR		0x0100
#define DBG_AREACTOR		0x0200
#define DBG_LNPSENSOR		0x0400
#define DBG_XE			0x0800
#define DBG_LOGGING		0x1000
#define DBG_TREELOCK		0x2000
#define DBG_DEL			0x4000
#define DBG_MODDBG		0x8000

#define DBG_ALL			0xffff

extern ECMBOOL	edbd_quick_debug_mode;

#define EDBDDBG(dbgset, fmt, ...)	ECMDBG(edbd_dbg, dbgset, fmt, ## __VA_ARGS__)
#endif	/* NO_EDBDDBG */

#else

#define EDBDDBG(dbgset, fmt, ...)       do {} while(0)

#endif

typedef void *edbd_worker_t;

extern ecm_ebc_t	edbd_ec;

extern const char	*edbd_snapshot, *edbd_initial_snapshot;
extern const char	*edbd_modname;
extern const char	*edbd_modver;
extern const char	*edbd_clxdir;
extern const char	*edbd_modules_dir;

extern ECMBOOL	is_clear_snapshot;

#define EDBD_UPDATE_SEQ_MAX	0xffffffff
#define EDBD_UPDATE_SEQ_WIN	0xffff
#define EDBD_UPDATE_SEQ_WRAP	(EDBD_UPDATE_SEQ_MAX - EDBD_UPDATE_SEQ_WIN)

#define EDBD_INCREASE_UPDATE_SEQ()	\
	edbd_update_seq = (edbd_update_seq == EDBD_UPDATE_SEQ_MAX) ? 1: edbd_update_seq + 1
#define EDBD_NEXT_UPDATE_SEQ(seq)			\
	((seq) == EDBD_UPDATE_SEQ_MAX ? 1: (seq) + 1)
#define EDBD_IS_FUTURE_UPDATE_SEQ(seq)			\
	(seq != 0 &&					\
	 ((seq) > edbd_update_seq ||			\
	  (edbd_update_seq - (seq) > EDBD_UPDATE_SEQ_WRAP)))
#define EDBD_IS_PAST_UPDATE_SEQ(seq)			\
	(((seq) == 0 && edbd_update_seq > 0) ||		\
	 ((seq) < edbd_update_seq &&			\
	  (edbd_update_seq - (seq) < EDBD_UPDATE_SEQ_WIN)))

extern ecm_uint32	edbd_update_seq;

sr_t *edbd_cb_default(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr_pkt);
sr_t *edbd_cb_clireq(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr, ecm_ptr_t ctx);
sr_t *edbd_cb_detect(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr, ecm_ptr_t ctx);
sr_t *edbd_cb_announce(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr, ecm_ptr_t ctx);
sr_t *edbd_cb_getdb(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr, ecm_ptr_t ctx);
sr_t *edbd_cb_getlog(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr, ecm_ptr_t ctx);
sr_t *edbd_cb_updatesync(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr, ecm_ptr_t ctx);
sr_t *edbd_cb_update(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr, ecm_ptr_t ctx);
sr_t *edbd_cb_fileop(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr, ecm_ptr_t ctx);
sr_t *edbd_cb_exec(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr, ecm_ptr_t ctx);
sr_t *edbd_cb_rexec(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr, ecm_ptr_t ctx);
sr_t *edbd_cb_handover(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr, ecm_ptr_t ctx);
sr_t *edbd_cb_inform(ecm_ebc_t ecm_ebc, ebc_addr_t *saddr, ebc_addr_t *daddr, sr_t *sr, ecm_ptr_t ctx);

typedef void *edbd_conn_t;
typedef void *edbd_reactor_t;

ECMBOOL edbd_setup_db(const char *snapshot_fname);
ECMBOOL edbd_take_snapshot(void);
void edbd_finalize_snapshot(void);
sr_t *edbd_export_snapshot(void);
ECMBOOL edbd_import_snapshot(edbd_conn_t edbd_conn, const char *ndname_master);

extern ECM_INLINE void lock_resolving(void);
extern ECM_INLINE void unlock_resolving(void);
ECMBOOL block_resolving(void);
void unblock_resolving(void);
void check_resolving(void);

edb_err_t traverse_tree(edbd_conn_t edbd_conn, const sr_t *sr_LNP, const char *edexpr, sr_t **sr_res, sr_travopt_t opt);
ECMBOOL search_pivot(const sr_t *csr, const sr_t *csr_LNP, sr_t **psr_pivot, sr_t **psr_trail_LNP);

edbd_conn_t edbd_conn_add(ebc_addr_t *paddr);
void edbd_conn_del(edbd_conn_t);
edbd_conn_t edbd_conn_get(ECMBOOL reaction);
void edbd_conn_put(edbd_conn_t);

void conn_exec_reactor(edbd_conn_t edbd_conn, edbd_reactor_t reactor);
void conn_exec_anchor(edbd_conn_t edbd_conn, sr_t *sr);
edb_err_t conn_append(edbd_conn_t edbd_conn, sr_t *sr_dir, sr_t *sr, ECMBOOL logging);
edb_err_t conn_apply_owner(edbd_conn_t edbd_conn, sr_t *sr, xid_t owner);
edb_err_t conn_set_sr(edbd_conn_t edbd_conn, sr_t *sr_assigned, sr_t *sr_operand, ECMBOOL logging);
edb_err_t conn_set_asrv(edbd_conn_t edbd_conn, sr_t *sr, const char *casrv);
edb_err_t conn_edbroot_del(edbd_conn_t edbd_conn, sr_t *sr, ECMBOOL logging, ECMBOOL force);
edb_err_t conn_set_target(edbd_conn_t edbd_conn, sr_t *sr, sr_t *sr_target);
void edbd_conn_add_reactor(edbd_conn_t edbd_conn, edbd_reactor_t reactor);

sr_t *conn_xecreate(edbd_conn_t conn, sr_t *sr_HMS, const char *name, srt_t srt, xid_t creator_xid, ECMBOOL logging);
sr_t *conn_xeappend(edbd_conn_t conn, sr_t *sr_HMS, sr_t *sr_xe, xid_t creator_xid, ECMBOOL logging);
edb_err_t conn_xedelete(edbd_conn_t conn, sr_t *sr_xe, ECMBOOL logging, ECMBOOL force);

ECMBOOL conn_call(edbd_conn_t edbd_conn, const char *target, sr_t *sr_args, sr_t **psr_ret, int timeout);

ECMBOOL conn_start_reactors(edbd_conn_t edbd_conn, sr_t *sr);
ECMBOOL conn_stop_reactors(edbd_conn_t edbd_conn, sr_t *sr);
edb_err_t conn_set_reactors(edbd_conn_t edbd_conn, sr_t *sr, sr_t *sr_edexprs);

ECM_INLINE void conn_lock_election(edbd_conn_t edbd_conn);
ECM_INLINE void conn_unlock_election(edbd_conn_t edbd_conn);

void conn_block_others(edbd_conn_t edbd_conn);
void conn_unblock_others(edbd_conn_t edbd_conn);

ECM_INLINE sr_t *edbd_conn_getcwd(edbd_conn_t);
ECM_INLINE ECMBOOL edbd_conn_setcwd(edbd_conn_t, sr_t *sr_cwd);
ECM_INLINE ecm_uint64 edbd_conn_getkey(edbd_conn_t);
ECM_INLINE void edbd_conn_setkey(edbd_conn_t, ecm_uint64 key);
ECM_INLINE const char *edbd_conn_getuser(edbd_conn_t);
ECM_INLINE void edbd_conn_setuser(edbd_conn_t, const char *username);
ECM_INLINE eds_mod_t *edbd_conn_getmodule(edbd_conn_t);
ECM_INLINE eds_mod_t *edbd_conn_setmodule(edbd_conn_t, eds_mod_t *mod);
ECM_INLINE void edbd_conn_invalidate(edbd_conn_t);

edbd_lnpsensor_infos_t conn_get_lnpsensor_infos(edbd_conn_t);
edbd_lnpsensor_infos_t create_lnpsensor_infos(void);
void free_lnpsensor_infos(edbd_lnpsensor_infos_t);

ECMBOOL edbd_load_module(void);
void edbd_unload_module(void);
ECMBOOL edbd_initialize_module(edbd_conn_t edbd_conn);
void edbd_finalize_module(edbd_conn_t edbd_conn);
ECMBOOL edbd_import_modules(edbd_conn_t edbd_conn, sr_t *sr_modinfos);
sr_t * edbd_export_modules(void);

typedef edb_err_t (*executer_t)(edbd_conn_t conn, sr_t *sr, sr_t **psr_res, ecm_ptr_t ctx, ECMBOOL onlyone);

edb_err_t create_sr(edbd_conn_t conn, sr_t *sr, sr_t **psr_res, ecm_ptr_t ctx, ECMBOOL onlyone);
edb_err_t create_xe_(sr_t *sr, sr_t **psr_res, ecm_ptr_t ctx, ECMBOOL onlyone);
edb_err_t _del_sr_recur(sr_t *sr);
ECM_INLINE edb_err_t do_all_child_ptrs(edbd_conn_t conn, sr_t *sr_ptrs, executer_t executer, ecm_ptr_t ctx, sr_t **psr_res);

edb_err_t set_self_edbd_mode(edbd_conn_t edbd_conn, edbd_mode_t new_mode);
edb_err_t do_encluster(edbd_conn_t conn, ecm_uint32 target_ip);

edb_err_t edbd_call(edbd_conn_t edbd_conn, sr_t *sr_mmid, ecm_uint32 msgtype, sr_t *sr_msg, sr_t **psr_msg);
edb_err_t edbd_call_timeout(edbd_conn_t edbd_conn, sr_t *sr_mmid, ecm_uint32 msgtype, sr_t *sr_msg, ecm_uint32 timeout, sr_t **psr_res, sr_t **psr_res_mmid);
ECMBOOL edbd_call_oneway(edbd_conn_t edbd_conn, sr_t *sr_mmid, ecm_uint32 msgtype, sr_t *sr_msg);

edb_err_t process_cmd(edbd_conn_t conn, sr_t *sr_cmd, sr_t **psr_res);

void edbd_start_areactor(void);

void edbd_start_reactors(edbd_conn_t);
void edbd_stop_reactors(edbd_conn_t);

ECM_INLINE ECMBOOL is_attr_modifiable(const sr_t *sr);
ECM_INLINE ECMBOOL is_attr_volatile(const sr_t *sr);

ECM_INLINE ECMBOOL is_attr_owner_xid(xid_t xid);
ECM_INLINE ECMBOOL is_attr_owner(const sr_t *sr);
ECM_INLINE ECMBOOL is_attr_owner_master(const sr_t *sr);
ECM_INLINE ECMBOOL is_attr_owner_modifier(const sr_t *sr);
ECM_INLINE ECMBOOL is_attr_update_private(const sr_t *sr);
ECM_INLINE ECMBOOL is_attr_update_instant(const sr_t *sr);
ECM_INLINE ECMBOOL is_attr_fetch_normal(const sr_t *sr);
ECM_INLINE ECMBOOL is_attr_fetch_ondemand(const sr_t *sr);

ECMBOOL eds_set_reactors(sr_t *sr, const sr_t *sr_reactors); 

ECMBOOL edbd_init(void);
void edbd_finalize(void);

ECMBOOL edbd_join_node(edbd_conn_t edbd_conn, const char *ndname);
ECM_INLINE ECMBOOL add_cluster(edbd_conn_t edbd_conn, const char *clname);
ECM_INLINE void del_cluster(edbd_conn_t edbd_conn, const char *clname);
void add_node(edbd_conn_t conn, const char *clname, const char *ndname);
ECM_INLINE void del_node(edbd_conn_t edbd_conn, const char *clname, const char *ndname);

ECM_INLINE sr_t *get_cluster(const char *clname);
ECM_INLINE sr_t *get_node(const char *clname, const char *ndname);

#ifdef ECM_DEBUG

char *dbg_get_ipstr(sr_t *sr_ip);
char *dbg_get_opt(int opt);
char *dbg_get_field(edb_field_t field);
char *dbg_get_LNP(sr_t *sr_LNP);
char *dbg_get_memLNP(sr_t *sr_memLNP);
char *dbg_get_tree_LNP(const sr_t *sr);
char *dbg_get_edexprs(const sr_t *sr_edexprs);
char *dbg_get_edexpr(const sr_t *sr_edexpr);
char *dbg_get_conn_info(edbd_conn_t edbd_conn);
char *dbg_get_log_info(const sr_t *sr_log);
const char *dbg_get_treelock_str(treelock_t type);
const char *dbg_get_sublock_str(int type);

ecm_uint32 get_reactor_count(const sr_t *sr, ECMBOOL force);
ecm_uint32 get_lnpsensor_count(const sr_t *sr, ECMBOOL force);

ECMBOOL thread_has_sublock(void);

#endif

edb_err_t edbd_shutdown(edbd_conn_t conn, sr_t *sr);
edb_err_t edbd_shutdown_self(void);

edb_err_t req_shutdown(edbd_conn_t edbd_conn, sr_t *sr_mmid);

void edbd_start_updater(void);
void edbd_stop_updater(void);
void wakeup_updater(void);

extern ECMBOOL volatile edbd_going_to_shutdown;

extern ECMBOOL volatile need_master_election;
extern char *master_successor;
extern ECMBOOL master_handovered;

ECMBOOL resolve_master(void);
void set_unresolved(void);
edb_err_t edbd_handover_master(void);

sr_t *edbd_get_logset(void);
void clear_logset_groups(void);
sr_t *find_logset_groups(ecm_uint32 start_seq, ecm_uint32 end_seq);
void edbd_putback_logset(sr_t *sr_logset);
void clear_pending_logs(void);

void add_log_APPEND(sr_t *sr_dir, sr_t *sr);
void add_log_SET(sr_t *sr);
void add_log_SETREF(sr_t *sr, const sr_t *sr_LNP);
void add_log_SETEXT(sr_t *sr);
void add_log_DEL(sr_t *sr);
void add_log_XECREATE(sr_t *sr_dir, const char *name, srt_t srt);
void add_log_XEDELETE(const char *LNP_xe);
void add_log_XEAPPEND(sr_t *sr_dir, sr_t *sr_xe);
void add_log_CS(const char *lockname, const char *type);

sr_t *get_master_log(void);
void keep_master_log(sr_t *sr_master_log);
void append_logset_group(edbd_conn_t edbd_conn, sr_t *sr_logset, xid_t node_xid);
void apply_master_log(edbd_conn_t edbd_conn, sr_t *sr_master_log);
void save_master_log(sr_t *sr_master_log);
ECMBOOL apply_pending_master_log(edbd_conn_t edbd_conn);
ECMBOOL uptodate_master_log(edbd_conn_t edbd_conn, ecm_uint32 update_seq);
sr_t *get_logged_snapshot(void);

sr_t *register_xe_form(sr_t *sr_forms);
ECM_INLINE sr_t *get_xe_form(srt_t srt);
ECM_INLINE sr_t *get_xe_forms(void);
void unregister_xe_form(sr_t *sr_xe_form_ptrs);

srt_t traverse_ghost_LNP(srt_t srt, sr_t *sr_LNI, ECMBOOL *pis_vector);
ECM_INLINE ECMBOOL is_xe_srt(srt_t srt);
ECM_INLINE ECMBOOL is_xe_sr(const sr_t *sr);

funcdef_t *fid_to_funcdef(eds_fid_t fid);
ECM_INLINE funcdef_t *base_fid_to_funcdef(eds_fid_t fid);

edb_err_t oct_to_file(const char *basedir, sr_t *sr_oct, ECMBOOL overwrite);
sr_t *file_to_oct(const char *filepath);

edb_err_t
edbd_filecopy(ebc_ndid_t src_ndid, const char *src_path,
	      ebc_ndid_t dst_ndid, const char *dst_path,
	      edb_fileopt_t opt);
edb_err_t edbd_fileremove(ebc_ndid_t ndid, const char *path, edb_fileopt_t opt);
edb_err_t edbd_filemkdir(ebc_ndid_t ndid, const char *vpath, edb_fileopt_t opt);

edb_err_t
edbd_fileexist(ebc_ndid_t ndid, const char *vpath);

sr_t *edbd_service_fileop(sr_t *sr_info);

sr_t *fetch_file(edbd_conn_t edbd_conn, sr_t *sr_file);

edb_err_t edbd_file_open(edbd_conn_t edbd_conn, ebc_ndid_t dst_ndid, const char *dst_path, ecm_uint32 flags, ecm_uint64 startoff, ecm_uint32 *pkey);
edb_err_t edbd_file_close(edbd_conn_t edbd_conn, ebc_ndid_t dst_ndid, ecm_uint32 key, ECMBOOL done);

ECMBOOL edbd_run_process(ebc_ndid_t ndid, sr_exectx_t *pctx);
ECMBOOL edbd_run_process_sr(ebc_ndid_t ndid, sr_t *sr_exectx, sr_t **psr_res);
sr_t *edbd_service_exec(sr_t *sr_info);

sr_t *edbd_service_rexec(sr_t *sr_info);

void ecx_initialize(void);
sr_t *process_ecx(edbd_conn_t edbd_conn, sr_t *sr_ecx_state);
sr_t *process_ecxup(edbd_conn_t edbd_conn, sr_t *sr_args);
sr_t *process_menu(edbd_conn_t edbd_conn, sr_t *sr_ecx_state, ecm_uint32 menuid);
sr_t *process_active_area(edbd_conn_t edbd_conn, const char *username);

void commit_lnpsensors(edbd_lnpsensor_infos_t lnpsensors);

xid_t xidstr_to_xid(const char *c_xidstr);
sr_t *xid_to_mmid(xid_t xid);

ECM_INLINE ECMBOOL ndname_to_xid(const char *ndname, xid_t *pxid);
ECM_INLINE void ndid_to_xid(ebc_ndid_t ndid, xid_t *pxid);

typedef enum {
	EDBD_WALKOPT_RECUR = 1,
	EDBD_WALKOPT_CHILD = 2,
	EDBD_WALKOPT_NO_DEREF = 4,
	EDBD_WALKOPT_NOT_THIS = 8,
	EDBD_WALKOPT_RECUR_NO_DEREF = EDBD_WALKOPT_RECUR | EDBD_WALKOPT_NO_DEREF,
} edbd_walkopt_t;

ECMBOOL edbd_walk(sr_t *sr, sr_walk_t walkfunc, ecm_ptr_t ctx, edbd_walkopt_t opt);
sr_t *edbd_walk_dup(sr_t *sr, sr_walkdup_t walkdupfunc, ecm_ptr_t ctx, edbd_walkopt_t opt);
ECM_INLINE sr_t *find_sr_from_ptrs(sr_t *sr_ptrs, const char *name);
ECM_INLINE ECMBOOL has_empty_HMS(const sr_t *sr);

ECM_INLINE void lock_tree(void);
ECM_INLINE void unlock_tree(void);
ECM_INLINE ECMBOOL get_tree_lock(const sr_t *sr, treelock_t type);
ECM_INLINE void put_tree_lock(const sr_t *sr, treelock_t type);
ECM_INLINE ECMBOOL get_tree_lock_ptrs(const sr_t *sr_ptrs, treelock_t type);
ECM_INLINE void put_tree_lock_ptrs(const sr_t *sr_ptrs, treelock_t type);

ECMBOOL tree_lock(const sr_t *sr, treelock_t type);
void tree_unlock(const sr_t *sr, treelock_t type);
ECMBOOL tree_mark_finalized(sr_t *sr);
void tree_mark_destroyed(sr_t *sr);

ECMBOOL tree_lock_ptrs(const sr_t *sr_ptrs, treelock_t type);
void tree_unlock_ptrs(const sr_t *sr_ptrs, treelock_t type);

ECMBOOL tree_is_valid(const sr_t *sr);

extern edb_err_t edbd_auth_user(edbd_conn_t edbd_conn, const char *username, const char *passwd, char **psessionid);
extern ECMBOOL edbd_auth(ECMBOOL session, ebc_addr_t *saddr, const char *user, const char *passwd_or_sessid);
extern char * edbd_auth_getsessionid(const char *username);
extern ECMBOOL edbd_auth_is_admin(const char *username);

sr_t *link_backref(edbd_conn_t edbd_conn, sr_t *sr_referer, const sr_t *sr_target);
sr_t *unlink_backref(edbd_conn_t edbd_conn, sr_t *sr_referer, sr_t *sr_target);
void apply_link_backref(edbd_conn_t edbd_conn, sr_t *sr_referer, sr_t *sr_target, sr_t *sr_linked_infos);
void apply_unlink_backref(edbd_conn_t edbd_conn, sr_t *sr_target, sr_t *sr_unlinked_infos);

#ifdef TREELOCK_TRACE

extern void check_treelock(void);
extern void trace_treelock(void);
extern void untrace_treelock(void);

#define TRACE_TREELOCK()	trace_treelock()
#define UNTRACE_TREELOCK()	untrace_treelock()
#define CHECK_TREELOCK()	check_treelock()

#else

#define TRACE_TREELOCK()	do {} while (0)
#define UNTRACE_TREELOCK()	do {} while (0)
#define CHECK_TREELOCK()	do {} while (0)

#endif

#endif	/* EDBD_H */
